package com.lanhao.aot.aiui.newversion;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.lang3.StringUtils;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 自定义与AIUI交互的websokcet
 * @author kunzhou3
 * @date 2023-09-18
 */
public class AIUIWebSocketClient extends WebSocketClient {
	
	private static final Logger LOG = LoggerFactory.getLogger(AIUIWebSocketClient.class);
	
	private CountDownLatch countDownLatch;
	private String uid;

    public AIUIWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch countDownLatch, String uid) {
        super(serverUri, protocolDraft);
        this.countDownLatch = countDownLatch;
        this.uid = uid;
    }
    
    public CountDownLatch getCountDownLatch() {
		return countDownLatch;
	}

	public void setCountDownLatch(CountDownLatch countDownLatch) {
		this.countDownLatch = countDownLatch;
	}

	@Override
    public void onOpen(ServerHandshake handshake) {
        // 会阻塞onMesage, 如果要在这里发送数据需要另起线程
        LOG.info("打开连接, code:{}", handshake.getHttpStatusMessage());
    }

    @Override
    public void onMessage(String msg) {
    	LOG.info("收到AIUI服务端返回的信息：" + msg);
        JSONObject response = JSONObject.parseObject(msg);
        JSONObject header = response.getJSONObject("header");
        String streamId = header.getString("stmid");
        // 结果解析
        JSONObject payload = response.getJSONObject("payload");
        if (payload != null) {
        	JSONObject resultObject = AIUIUtil.resultMap.get(streamId);
        	// 雅典娜解析结果
        	JSONObject cbmSemantic = payload.getJSONObject("cbm_semantic");
            if (cbmSemantic != null) {
            	String semantic = new String(Base64.getDecoder().decode(cbmSemantic.getString("text")));
            	LOG.info("语义结果 cbm_semantic：" + semantic);
            	resultObject.put("cbm_semantic", semantic);
            	JSONObject semanticObject = JSON.parseObject(semantic);
            	String service = semanticObject.getString("service");
            	if(StringUtils.isNotBlank(service)) {
            		countDownLatch.countDown();
            		return;
            	}
            }
            // 语义最终结果
            JSONObject nlp = payload.getJSONObject("nlp");
            if (nlp != null) {
            	String nlpText = new String(Base64.getDecoder().decode(nlp.getString("text")));
            	LOG.info("语义结果 nlp：" + nlpText);
            	resultObject.put("nlp", (StringUtils.isNotBlank(resultObject.getString("nlp")) ? resultObject.getString("nlp") : StringUtils.EMPTY) + nlpText);
            }
            // 语音听写结果
            JSONObject iat = payload.getJSONObject("iat");
            if (iat != null) {
            	LOG.info("识别结果 iat：" + new String(Base64.getDecoder().decode(iat.getString("text"))));
            }
        }
        if (!header.containsKey("status")) {
            return;
        }
        int status = header.getIntValue("status");
        if (status == 2) {
        	int code = header.getIntValue("code");
        	if(code != 0) {
        		JSONObject msgObject = header.getJSONObject("message");
        		String errMsg = msgObject.getString("errMsg");
    			JSONObject resultObject = new JSONObject();
    			resultObject.put("nlp", errMsg);
        		AIUIUtil.resultMap.put(streamId, resultObject);
        	}
            // 接收到最后一帧结果
        	// 将结果放到缓存中，方便前端取值
            countDownLatch.countDown();
        }
    }

    @Override
    public void onError(Exception e) {
    	LOG.info("连接发生错误：" + e.getMessage() + ", " + new Date());
        e.printStackTrace();
    }

    /**
     * conn The WebSocket instance this event is occurring on.
     * code The codes can be looked up here: CloseFrame
     * reason Additional information string
     * remote Returns whether or not the closing of the connection was initiated by the remotehost.
     */
    @Override
	public void onClose(int code, String message, boolean b) {
    	LOG.info("连接已关闭，code={}，message={}，b={}", code, message, b);
		if (!b) {
			AIUIUtil.reauthconnectMap.put(uid, Boolean.TRUE);
			LOG.info("连接异常关闭，需要重新鉴权连接, uid={}", uid);
		}
        countDownLatch.countDown();
    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        try {
            String responseText = new String(bytes.array(), "utf-8");
            LOG.info("服务端返回：" + responseText);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
